package org.jpropelleralt.box;

import java.util.Iterator;

import org.jpropelleralt.reaction.Reaction;
import org.jpropelleralt.universe.Universe;
import org.jpropelleralt.view.View;

/**
 * Features of a {@link Box}
 */
public interface BoxFeatures {
	/**
	 * Get the {@link Universe} this {@link Box} belongs to
	 * @return {@link Universe}
	 */
	public Universe universe();

	/**
	 * Add a {@link View} to this {@link Box}
	 * @param view	The {@link View}
	 */
	public void addView(View view);

	/**
	 * Remove a {@link View} from this {@link Box}
	 * @param view	The {@link View}
	 */
	public void removeView(View view);

	/**
	 * Get an {@link Iterator} over registered {@link View}s
	 * @return	{@link Iterator} of {@link View}s
	 */
	public Iterable<View> views();
	
	/**
	 * Add a {@link Reaction} to be notified of
	 * changes to this {@link Box}
	 * @param reaction	The {@link Reaction}
	 */
	public void addReaction(Reaction reaction);

	/**
	 * Remove a {@link Reaction}, no longer to be notified of
	 * changes to this {@link Box}
	 * @param reaction	The {@link Reaction}
	 */
	public void removeReaction(Reaction reaction);
	
	/**
	 * Get an {@link Iterator} over registered {@link Reaction}s
	 * @return	{@link Iterator} of {@link Reaction}s
	 */
	public Iterable<Reaction> reactions();
	
	/**
	 * Register a {@link Reaction} to be kept in scope
	 * by this {@link Box}. Since {@link Reaction}s are not
	 * kept in scope by just listening to a {@link Box}
	 * using {@link #addReaction(Reaction)}, they must
	 * be registered with a {@link Box} or they will be
	 * garbage collected. They should register with each
	 * {@link Box} that they are required by - generally
	 * this consists of the targets of the {@link Reaction} - 
	 * the {@link Box}es that could be affected when the 
	 * {@link Reaction} is applied 
	 * (using {@link Reaction#apply(boolean)}). 
	 * @param reaction	The {@link Reaction}
	 */
	public void registerReaction(Reaction reaction);

	/**
	 * Unregister a {@link Reaction}, it will no longer be
	 * kept in scope by this {@link BoxFeatures}. See
	 * also {@link #registerReaction(Reaction)}
	 * @param reaction	The {@link Reaction}
	 */
	public void unregisterReaction(Reaction reaction);
	
}
